package cn.net.ecode.common.datasource;

import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import cn.net.ecode.common.config.Global;
import cn.net.ecode.common.utils.StringUtils;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * 多数据源配置对象
 * @author ThinkGem
 * @version 2015-6-15
 */
public class RoutingDataSource extends AbstractRoutingDataSource {
	
	/**
	 * 所有数据源集合（不包括默认数据源）
	 */
	private Map<Object, Object> targetDataSources;

	/**
	 * 获取数据源名称
	 */
	protected Object determineCurrentLookupKey() {
		String dataSourceName = DataSourceHolder.getDataSourceName();
		logger.debug("currentDataSourceName: " + (dataSourceName == null ? "default" : dataSourceName));
		return dataSourceName;
	}

	/**
	 * 初始化设置数据源
	 */
	public void setTargetDataSources(Map<Object, Object> targetDataSources) {
		logger.debug("setTargetDataSources: " + targetDataSources.size());
		super.setTargetDataSources(this.targetDataSources = targetDataSources);
	}

	/**
	 * 添加一个数据源
	 */
	public void addTargetDataSource(String dataSourceName, DataSource dataSource) {
		logger.debug("addTargetDataSource: " + dataSourceName);
		this.targetDataSources.put(dataSourceName, dataSource);
		super.afterPropertiesSet();
	}
	
	/**
	 * 移除一个数据源
	 */
    public void removeTargetDataSource(String dataSourceName){
		logger.debug("removeTargetDataSource: " + dataSourceName);
    	this.targetDataSources.remove(dataSourceName);
        super.afterPropertiesSet();
    }

	/**
	 * 实例化数据源对象
	 * @return
	 */
	public DataSource newDataSource(String driverClassName, String url, String username, String password,
			int initialSize, int minIdle, int maxActive) {
		DataSource dataSource = determineTargetDataSource();
		if (dataSource instanceof DruidDataSource){
			DruidDataSource druidDataSource = ((DruidDataSource)dataSource).cloneDruidDataSource();
			druidDataSource.setDriverClassName(driverClassName);
			druidDataSource.setUrl(url);
			druidDataSource.setUsername(username);
			druidDataSource.setPassword(password);
			druidDataSource.setTestWhileIdle(false);
			// 连接池初始化连接数
			if (initialSize > 0){
				druidDataSource.setInitialSize(initialSize);
			}
			// 连接池最小连接数
			if (minIdle > 0){
				druidDataSource.setMinIdle(minIdle);
			}
			// 连接池最大连接数
			if (maxActive > 0){
				druidDataSource.setMaxActive(maxActive);
			}
			logger.debug("newDataSource.druidDataSource: " + druidDataSource.getUrl() + "  " + druidDataSource.getUsername());
			return druidDataSource;
		}else{
			DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
			driverManagerDataSource.setDriverClassName(driverClassName);
			driverManagerDataSource.setUrl(url);
			driverManagerDataSource.setUsername(username);
			driverManagerDataSource.setPassword(password);
			logger.debug("newDataSource.driverManagerDataSource: " + driverManagerDataSource.getUrl() + "  " + driverManagerDataSource.getUsername());
			return driverManagerDataSource;
		}
	}
	
	/**
	 * 初始化数据源配置
	 */
	@Override
	public void afterPropertiesSet() {
		// 先执行父类初始化下配置
		super.afterPropertiesSet();
		// 初始化多数据源数据库配置
		String dataSourceNames = Global.getProperty("jdbc.dataSourceNames");
		logger.debug("init config dataSourceNames: " + dataSourceNames);
		if (StringUtils.isNotBlank(dataSourceNames)){
			for (String dataSourceName : StringUtils.split(dataSourceNames, ",")){
				String type = Global.getProperty("jdbc." + dataSourceName + ".type");
				String driverClassName = Global.getProperty("jdbc." + dataSourceName + ".driver");
				String url = Global.getProperty("jdbc." + dataSourceName + ".url");
				String username = Global.getProperty("jdbc." + dataSourceName + ".username");
				String password = Global.getProperty("jdbc." + dataSourceName + ".password");
				// 连接池初始大小、最小和最大连接个数
				int initialSize = NumberUtils.toInt(Global.getProperty("jdbc." + dataSourceName + ".pool.init"), -1);
				int minIdle = NumberUtils.toInt(Global.getProperty("jdbc." + dataSourceName + ".pool.minIdle"), -1);
				int maxActive = NumberUtils.toInt(Global.getProperty("jdbc." + dataSourceName + ".pool.maxActive"), -1);
				// 创建连接添加到系统数据源
				if (StringUtils.isNoneBlank(type, driverClassName, url, username)){
					DataSource dataSource = newDataSource(driverClassName, url, username, password, initialSize, minIdle, maxActive);
					logger.debug("init config addTargetDataSource: " + dataSourceName);
					this.targetDataSources.put(dataSourceName, dataSource);
				}
			}
			// 再执行父类方法刷新配置
			super.afterPropertiesSet();
		}
	}
	
}
